<?php

namespace App\Library\Logic;

use App\Library\Models\AdminAuctionModel;
use App\Library\Requests\Auction\AuctionAddRequest;
use App\Library\Requests\Auction\AuctionBidPageRequest;
use App\Library\Requests\Auction\AuctionEditRequest;
use App\Library\Requests\Auction\AuctionIndexPageRequest;
use App\Library\Requests\Auction\AuctionPageRequest;
use App\Library\Requests\Base\SerialNumberRequest;
use App\Models\AuctionModel;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

class AuctionLogic extends AuctionModel
{
    /**
     * indexPaging
     * @param AuctionIndexPageRequest $request
     * @return array
     */
    public static function indexPaging(AuctionIndexPageRequest $request): array
    {
        $builder = self::query()->where([
            'status' => 1,
            'audit_status' => 1,
            'sell_out' => 0,
            'expired' => 0,
            'is_end' => 0,
        ])->whereIn('is_start',[0,1]);
        $builder->orderBy('is_start');
        if (!is_null($request->sort)) {
            if ($request->sort === 1) $builder->orderBy('start_price');
            else if ($request->sort === 2) $builder->orderByDesc('start_price');
            else if ($request->sort === 3) $builder->orderByDesc('audit_at');
            $builder->orderByDesc('recommend')->orderBy('sort')->orderByDesc('created_at');
            $request->offsetUnset('sort');
        }

        if (!is_null($request->sellerId)) {
            $builder->where('publish_id', $request->sellerId);
            $request->offsetUnset('sellerId');
        }
        if (!is_null($request->serialNumber)) {
            $builder->where('serial_number', '<>', $request->serialNumber);
            $request->offsetUnset('serialNumber');
        }
        $paginate = paginate(helpBuilder($builder, $request)->paginate($request->limit, [
            'serial_number', 'file_id', 'title', 'start_price', 'start_at', 'end_at', 'tag', 'current_price','shot_count'
        ]));
        foreach ($paginate['data'] as $v) {
            $v->bidNum = cache('bid:' . $v->serial_number);
        }
        return $paginate;
    }

    /**
     * bidPaging
     * @param AuctionBidPageRequest $request
     * @param int $id
     * @return array
     */
    public static function bidPaging(AuctionBidPageRequest $request, int $id): array
    {
        $builder = AuctionBidLogic::query()->leftJoin('shop_user', 'shop_user.user_id', 'auction_bid.user_id')
            ->leftJoin('auction', 'auction.id', 'auction_bid.auction_id')
            ->where('auction_id', $id)->orderByDesc('auction_bid.id');
        $paginate = paginate($builder->paginate($request->post('limit'), [
            'num', 'auction_bid.created_at', 'user_mobile', 'user_avatar', 'auction_bid.user_id',
            'start_price', 'inc', 'price',
        ]));
        foreach ($paginate['data'] as $v) {
            $v->user_mobile = substr($v->user_mobile, 0, 3) . '*****' . substr($v->user_mobile, 8);
            $v->my = $v->user_id === userId();
            unsetObject($v, ['user_id', 'num', 'start_price', 'inc']);
        }
        return $paginate;
    }

    /**
     * paging
     * @param AuctionPageRequest $request
     * @return array
     */
    public function paging(AuctionPageRequest $request): array
    {
        $builder = $this->newQuery()->where('publish_id', userId());
        if (is_null($request->sortColumn)) $builder->orderByDesc('created_at');
        return paginate(helpBuilder($builder, $request)->paginate($request->post('limit')));
    }

    /**
     * add
     * @param AuctionAddRequest $request
     * @return void
     */
    public function add(AuctionAddRequest $request): void
    {
        $request->fileId = $request->mainImgIds[0] ?? null;
        $request->publishId = USERID;
        $this->handleCategory($request);
        $array = handleRequest($request);
        if ($request->cappingPrice * 1 <= 0) $array['cappingPrice'] = null;
        $item = self::insertForModel($array);
        $this->handleMedia($request, $item->id);
    }

    /**
     * edit
     * @param AuctionEditRequest $request
     * @param Model $item
     * @return void
     */
    public function edit(AuctionEditRequest $request, Model $item): void
    {
        $request->fileId = $request->mainImgIds[0] ?? null;
        $request->publishId = USERID;
        $request->auditStatus = 0;
        $request->onePush = $request->onePush ?? null;
        $request->twoPush = $request->twoPush ?? null;
        $this->handleCategory($request);
        $array = handleRequest($request);
        if ($request->cappingPrice * 1 <= 0) $array['cappingPrice'] = null;

        self::updateForModel($array, $item);
        $this->handleMedia($request, $item->id);
    }

    /**
     * 校验参拍人资格
     * @param SerialNumberRequest $request
     * @return bool
     *
     */
    public function checkBail(SerialNumberRequest $request): bool
    {
        $item = $this->findBySerialNumber($request);
        if (is_null($item)) return false;
        else if ($item->bail_price <= 0) return true;
        else if ($item->status !== 1) return false;
        else if ($item->expired === 1) return false;
        else if ($item->audit_status !== 1) return false;
        else if (now()->parse($item->start_at)->format('Y-m-d H') !== now()->format('Y-m-d H')) return false;
        else if (is_null($item->bail)) return false;
        return true;
    }

    /**
     * 数量统计
     * @return mixed
     */
    public function numTj(): array
    {
        return (array)DB::select(__('sql.tj.auctionNum', ['userId' => USERID,]))[0];
    }

    /**
     * 复制
     * @param Model $self
     * @param int|null $userId
     * @return string
     */
    public static function copy(Model $self, ?int $userId = null): string
    {
        $id = $self->id;
        self::unsetObject($self);
        $arr = ['startAt' => now()->startOfDay(), 'endAt' => now()->addDays(3)->startOfDay()];
        if (!is_null($userId)) {
            $new = AdminAuctionModel::insertForModel(array_merge($self->toArray(), $arr, ['publishId' => $userId]));
            $where = ['objectType' => 1, 'objectId' => $new->id];
            $arr = [];
            if (!empty($self->main_img_ids)) {
                foreach (explode(',', $self->main_img_ids) as $v) $arr[] = array_merge($where, ['fileId' => $v, 'type' => 0]);
            }
            if (!empty($model->desc_img_ids)) {
                foreach (explode(',', $self->desc_img_ids) as $v) $arr[] = array_merge($where, ['fileId' => $v, 'type' => 1]);
            }
            if (!empty($self->video_id)) $arr[] = array_merge($where, ['fileId' => $self->video_id, 'type' => 2]);
        } else {
            $new = self::insertForModel(array_merge($self->toArray(), $arr, ['publishId' => USERID]));
            $where = ['objectType' => 1, 'objectId' => $new->id];
            $list = MediaRelationLogic::getByWhere(['objectType' => 1, 'objectId' => $id]);
            $arr = [];
            foreach ($list as $v) $arr[] = array_merge($where, ['fileId' => $v->file_id, 'type' => $v->type]);
        }
        MediaRelationLogic::insert($arr ?? []);
        return $new->serial_number;
    }


    /**
     * handleCategory
     * @param AuctionAddRequest $request
     * @return void
     */
    private function handleCategory(AuctionAddRequest $request): void
    {
        $two = (int)ShopCategoryLogic::valueByWhere('categoryId', $request->categoryId, 'categoryParentId');
        $one = (int)ShopCategoryLogic::valueByWhere('categoryId', $two, 'categoryParentId');
        $request->categoryIdOne = $one;
        $request->categoryIdTwo = $two;
        $request->categoryIdThree = $request->categoryId;
        $request->offsetUnset('categoryId');
    }

    /**
     * handleMedia
     * @param AuctionAddRequest $request
     * @param int $id
     * @return void
     */
    private function handleMedia(AuctionAddRequest $request, int $id): void
    {
        $where = ['objectType' => 1, 'objectId' => $id];
        MediaRelationLogic::deleteByWhere($where);
        if (!empty($request->mainImgIds)) {
            $arr = [];
            foreach ($request->mainImgIds as $v) $arr[] = array_merge($where, ['fileId' => $v]);
            MediaRelationLogic::insert($arr ?? []);
        }
        if (!empty($request->descImgIds)) {
            $arr = [];
            foreach ($request->descImgIds as $v) $arr[] = array_merge($where, ['fileId' => $v, 'type' => 1]);
            MediaRelationLogic::insert($arr ?? []);
        }
        if (!is_null($request->videoId)) {
            MediaRelationLogic::insertForModel(array_merge($where, ['fileId' => $request->videoId, 'type' => 2]));
        }
    }

    /**
     * 详情
     * @param Model $item
     * @return void
     */
    public static function getMedia(Model $item): void
    {
        unsetObject($item, ['main_img_ids', 'desc_img_ids']);
        $mainImgIds = $descImgIds = [];
        foreach ($item->media as $v) {
            if ($v->type === 0) $mainImgIds[] = $v->file_id;
            else if ($v->type === 1) $descImgIds[] = $v->file_id;
            else if ($v->type === 2) $item->video_id = $v->file_id;
        }
        $item->mainImgIds = $mainImgIds;
        $item->descImgIds = $descImgIds;
        unset($item->media);
    }

    /**
     * unsetProduct
     * @param Model $shopProduct
     * @return void
     */
    private static function unsetObject(Model $shopProduct): void
    {
        unsetObject($shopProduct, [
            'id',
            'serial_number',
            'status',
            'sell_out',
            'expired',
            'audit_status',
            'start_at',
            'end_at',
            'is_start',
            'is_end',
            'publish_id',
            'ok_reason',
            'fail_reason',
            'audit_at',
            'sort',
            'recommend',
            'shot_count',
            'user_count',
            'created_at',
            'updated_at',
            'deleted_at'
        ]);
    }
}
